package com.cochain.ftp;


import cn.hutool.core.util.StrUtil;

import cn.hutool.extra.ftp.FtpException;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.net.ftp.FTPClient;
import org.apache.commons.net.ftp.FTPReply;
import org.apache.commons.pool2.BasePooledObjectFactory;
import org.apache.commons.pool2.PooledObject;
import org.apache.commons.pool2.impl.DefaultPooledObject;
import org.springframework.beans.factory.annotation.Autowired;

import java.io.IOException;
import java.time.Duration;

/**
 * @title: FtpClientFactory
 * @Description: ftp客户端工厂
 * @Author Lmm
 * @Date: 2024/3/28 14:20
 * @Version 1.0
 */
@Slf4j
@Data
public class FtpClientFactory extends BasePooledObjectFactory<FTPClient> {

    @Autowired
    private final FtpProperties ftpProperties;

    @Override
    public void activateObject(PooledObject<FTPClient> p) throws Exception {
        super.activateObject(p);
    }
    // 验证对象可用否
    @Override
    public boolean validateObject(PooledObject<FTPClient> p) {
        FTPClient ftpClient = p.getObject();
        boolean connect = false;
        try {
            connect = ftpClient.sendNoOp(); // 保证控制连接的 keepalive
        } catch (IOException e) {
            e.printStackTrace();
        }
        return connect;
    }

    public FtpClientFactory(FtpProperties ftpProperties) {
        this.ftpProperties = ftpProperties;
    }
    // 生成方法
    @Override
    public FTPClient create(){
        final FTPClient ftpClient = new FTPClient();
        ftpClient.setControlEncoding(ftpProperties.getEncoding());
        ftpClient.setConnectTimeout(ftpProperties.getConnectTimeout());
        ftpClient.setControlKeepAliveTimeout(Duration.ofMinutes(ftpProperties.getControlKeepAliveTimeout()).toMillis());// 设置控制连接的保活时间
        try {
            // 连接ftp服务器
            ftpClient.connect(ftpProperties.getHost(), ftpProperties.getPort());
            // 登录ftp服务器
            ftpClient.login(ftpProperties.getUsername(), ftpProperties.getPassword());
        } catch (IOException e) {
            throw new FtpException("创建ftp连接失败", e);
        }
        // 是否成功登录服务器
        final int replyCode = ftpClient.getReplyCode();
        if (!FTPReply.isPositiveCompletion(replyCode)) {
            try {
                ftpClient.disconnect();
                throw new FtpException(StrUtil.format("Login failed for user [{}] ,host [{}], reply code is: [{}]",
                        ftpProperties.getUsername(),ftpProperties.getHost(), replyCode));
            } catch (IOException e) {
                throw new FtpException(StrUtil.format("Login failed for user [{}] ,host [{}], reply code is: [{}]",
                        ftpProperties.getUsername(),ftpProperties.getHost(), replyCode));
            }

        }
        ftpClient.setBufferSize(ftpProperties.getBufferSize());
        //设置模式
        if (ftpProperties.isPassiveMode()) {
            ftpClient.enterLocalPassiveMode();
        }
        if (ftpProperties.isUseEPSVwithIPv4()){
            ftpClient.setUseEPSVwithIPv4(true);
        }
        if (!ftpProperties.isRemoteVerificationEnabled()){
            ftpClient.setRemoteVerificationEnabled(false);
        }
        return ftpClient;
    }

    // 包装方法
    @Override
    public PooledObject<FTPClient> wrap(FTPClient ftpClient) {
        return new DefaultPooledObject<>(ftpClient);
    }

    // 销毁方法
    @Override
    public void destroyObject(PooledObject<FTPClient> ftpPooled){
        if (ftpPooled == null) {
            return;
        }
        FTPClient ftpClient = ftpPooled.getObject();
        try {
            if (ftpClient.isConnected()) {
                ftpClient.logout();
            }
        } catch (IOException io) {
            log.error("ftp client logout failed...", io);
        } finally {
            try {
                ftpClient.disconnect();
            } catch (IOException io) {
                log.error("close ftp client failed...", io);
            }
        }
    }
}

